home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 526-550 / disk_542 / chemnimate / cmtsource.lzh / parser11.c < prev    next >
C/C++ Source or Header  |  1991-08-27  |  14KB  |  570 lines

  1. /****************************************************************
  2.  *                                *
  3.  *    CheMnimaTe    to Animate Chemical Reactions        *
  4.  *                                *
  5.  *                                *
  6.  *    this program is written to show how molecules         *
  7.  *        are in 3-d    and how mechanisms work.    *
  8.  *                                *
  9.  *                                *
  10.  *                                *
  11.  *                                *
  12.  *==============================================================*
  13.  *Vers.    Date    Author    Comment                    *
  14.  *sk1    22Mar91    KvGend    started working on it.            *******
  15.  *sk5    24Mar91    KvGend    is now able to rotate some complicated formula*
  16.  *sk9    30Mar91 KvGend    Now accepts scripts. Is able to play    *******
  17.  *            along with penicilline            *
  18.  *ch6   09Apr91 KvGend    Scripts now use full commands.        *
  19.  *pars6    08May91    KvGend    Tokenized the whole stuff. code cleanup, *
  20.  *            but the code became longer (who cares?)    *
  21.  *pars7    02Jun91    KvGend    Now accepts expressions!!!        *
  22.  *            And a limited acception of vars...    *
  23.  *    06Jun91 KvGend    Loop & Until implemented        *
  24.  *par10    27Jul91    KvGend    Skip & EndSkip, and many other improvements*
  25.  *par11    11Aug91    KvGend    implemented Text (finally)        *
  26.  *    27Aug91    KvGend    Anim. Not implemented, just added    *
  27.  ****************************************************************/
  28. #define PARSER
  29.  
  30. #include <exec/types.h>
  31. #include "uni4.h"        /* the ChemNiMate include */
  32.  
  33. extern char header[];
  34. extern char footer[];
  35.  
  36. extern int array[MXNUMB][8];
  37.  
  38.  
  39. extern char *tlist[];
  40. extern struct DisplayInfo di;
  41.  
  42. int values[VALUESMAX];        /*array with return-values */
  43. struct ParserInfo pi =
  44. {0, 1, 0, -1, FALSE, 0, 0};
  45.  
  46. /***********************prototypes**********/
  47. extern LetItShow (int, int, int);
  48. int rightnr (int, int);
  49.  
  50. /************************int parser(char *)***/
  51. int
  52. parser (char *regel, int listnr)
  53. {
  54.   int i, j, strcount = 0, token;
  55.  
  56. /******** Tokenizing******/
  57.   token = tlist[listnr][0] & 0xFF;
  58.   pi.valnr = getvalues (regel, values);    /*get values in the line */
  59.  
  60.   pi.error = -1;
  61.   if (token != 0)        /* check right number of arguments */
  62.     rightnr (pi.valnr, tlist[listnr][1] & 0x0f);
  63.  
  64.   if (pi.skip == TRUE)
  65.     {                /*handle a skip */
  66.       if (token == 0x46)
  67.     pi.skip = FALSE;
  68.       return (0);
  69.     }
  70.  
  71. /********************* interpreting ******************/
  72.   if (pi.error == -1)
  73.     switch (token)
  74.       {
  75.       case 0:            /*no token available */
  76.     if (pi.datanr)        /***** data-line ? *****/
  77.       {
  78.         if (pi.valnr != 5)
  79.           {
  80.         pi.error = DATA_ERR;
  81.         break;
  82.           }
  83.         for (i = 0; i < 5; i++)
  84.           array[pi.datanr][i] = values[i];
  85.         pi.datanr++;
  86.         break;
  87.       }
  88.     pi.error = HEADACHE_ERR;/***** no, headache (==Syntax Error) *****/
  89.     break;
  90.  
  91.       case 0x10:        /***** data *****/
  92.     pi.datanr = values[0];
  93.     if (pi.datanr == 0 || pi.datanr >= MXNUMB)
  94.       pi.error = VAL_ERR;
  95.     break;
  96.  
  97.       case 0x11:        /***** EndData *****/
  98.     if (pi.datanr != 0)
  99.       pi.datanr = 0;
  100.     else
  101.       pi.error = EDWD_ERR;
  102.     break;
  103.  
  104.       case 0x12:
  105.     printf ("==> ANIM command used... auto-config to MeSsyDOS NOT IMPLEMENTED YET\n");
  106.     break;
  107.  
  108.       case 0x20:        /***** Repeat *****/
  109.     i = 0;
  110.     if (values[0] <= 1)
  111.       pi.error = VAL_ERR;
  112.     else
  113.       i = values[0] + 1024 * pi.linenr;
  114.     /* throw the repeatpos on the stack */
  115.     stack (ST_PUSH, ST_REPEAT, i);
  116.     break;
  117.  
  118.       case 0x21:        /***** EndRepeat *****/
  119.     i = stack (ST_POP, ST_REPEAT, 0);
  120.     if (i != ST_NOST)    /* there was a repeat on the stack*/
  121.       {
  122.         if (i % 1024 > 1)
  123.           {
  124.         pi.linenr = i / 1024;    /* restore to linenr */
  125.         stack (ST_PUSH, ST_REPEAT, --i);    /* and put it back where it belongs*/
  126.           }
  127.         break;
  128.       }
  129.     pi.error = ERWR_ERR;
  130.     break;
  131.  
  132.       case 0x22:        /***** Loop *****/
  133.     /* throw the repeatpos on the stack */
  134.     stack (ST_PUSH, ST_LOOP, pi.linenr * 1024 + 0);
  135.     break;
  136.  
  137.       case 0x23:        /***** Until <1> >= <2> *****/
  138.     i = stack (ST_POP, ST_LOOP, 0);
  139.     if (i == ST_NOST)
  140.       {
  141.         pi.error = ERWR_ERR;
  142.         break;
  143.       }
  144.     if (i % 1024 >= INFINITYMAX)
  145.       {
  146.         pi.error = INFINITY_ERR;
  147.         break;
  148.       }
  149.     if (values[0] < values[1])
  150.       {
  151.         pi.linenr = i / 1024;
  152.         stack (ST_PUSH, ST_LOOP, ++i);
  153.       }
  154.     break;
  155.  
  156.       case 0x30:        /***** Lines on/off*****/
  157.     switch (values[0])
  158.       {
  159.       case ON:
  160.         di.modes |= LINES;    /* turn lines on */
  161.         break;
  162.       case OFF:
  163.         di.modes &= ~LINES;    /* turn lines off */
  164.         break;
  165.       default:
  166.         pi.error = VAL_ERR;
  167.       }
  168.     break;
  169.  
  170.       case 0x31:        /***** Balls On/Off *****/
  171.     switch (values[0])
  172.       {
  173.       case ON:
  174.         di.modes |= BALLS;
  175.         break;
  176.       case OFF:
  177.         di.modes &= ~BALLS;
  178.         break;
  179.       default:
  180.         pi.error = VAL_ERR;
  181.       }
  182.     break;
  183.  
  184.       case 0x32:        /***** wait time *****/
  185.     for (i = 0; i < values[0]; i++)
  186.       WAITFRAME ();
  187.     break;
  188.  
  189.       case 0x34:        /***** DISPLAYMODE *****/
  190.     if (values[0] != 0 && values[0] != 1)
  191.       {
  192.         pi.error = VAL_ERR;
  193.         break;
  194.       }
  195.     di.modes &= ~31;
  196.     di.modes |= values[0] & 31;
  197.     break;
  198.  
  199.       case 0x41:        /***** DEBUG *****/
  200.     for (i = values[0]; i <= values[1]; i++)
  201.       {
  202.         printf ("\n%3d:  ", i);
  203.         for (j = 0; j < 8; j++)
  204.           printf ("%4d ", array[i][j]);
  205.       }
  206.     printf ("\n");
  207.     break;
  208.  
  209.       case 0x45:        /***** Skip *****/
  210.     pi.skip = TRUE;
  211.     break;
  212.       case 0x46:        /***** EndSkip *****/
  213.     pi.error = NOSKIP_ERR;    /* when the program ever gets here, */
  214.     break;            /* it means that there isn't a SKIP encountered */
  215.  
  216.       case 0x50:        /***** Show *****/
  217.     if (values[2] < values[1] || values[0] < 1)
  218.       pi.error = VAL_ERR;
  219.     else
  220.       LetItShow (values[0], values[1], values[2]);
  221.     break;
  222.  
  223.       case 0x51:        /***** ShowNS *****/
  224.     if (values[1] < values[0])
  225.       pi.error = VAL_ERR;
  226.     else
  227.       LetItShow (0, values[0], values[1]);
  228.     break;
  229.  
  230.       case 0x52:        /* SPages */
  231.     SwapShow ();
  232.     break;
  233.  
  234.       case 0x62:        /***** Set MiddleOfScreen (oorsprong)*****/
  235.     if (values[0] > VWIDTH || values[0] < 0 || values[1] > VHEIGHT || values[1] < 0)
  236.       {
  237.         pi.error = VAL_ERR;
  238.         break;
  239.       }
  240.     di.mx = values[0] + LBOR;
  241.     di.my = values[1] + UBOR;
  242.     break;
  243.  
  244.       case 0x70:        /***** THeader *****/
  245.     TakeStr (regel, header);
  246.     break;
  247.       case 0x71:        /***** TFooter *****/
  248.     TakeStr (regel, footer);
  249.     break;
  250.       case 0x72:
  251.     if (values[0] > VWIDTH || values[0] < 0 || values[1] > VHEIGHT || values[1] < 0)
  252.       {
  253.         pi.error = VAL_ERR;
  254.         break;
  255.       }
  256.     TakeStr (regel, regel);
  257.     TextAt (values[0], values[1], regel);
  258.     break;
  259.       case 0x73:        /***** T *****/
  260.     TakeStr (regel, regel);
  261.     printf ("#tekst: '%s'\n", regel);
  262.     break;
  263.  
  264.       case 0x80:        /***** change *****/
  265.       case 0x81:
  266.       case 0x82:
  267.     DoChange (regel, token);
  268.     break;
  269.  
  270.       case 0x90:        /***** I:= *****/
  271.     pi.I = values[0];
  272.     break;
  273.       case 0x91:        /***** J:= *****/
  274.     pi.J = values[0];
  275.     break;
  276.       case 0x92:
  277.       case 0x60:        /***** ANG:= *****/
  278.     di.angle = (values[0] & 63) + 65536;
  279.     break;
  280.       case 0x93:
  281.       case 0x61:        /***** DAN:= *****/
  282.     if (values[0] > 10 || values[0] < -10)
  283.       pi.error = VAL_ERR;
  284.     else
  285.       di.dangle = values[0];
  286.     break;
  287.  
  288.       default:
  289.     printf ("$$ This should not occur !!!\nToken : %X Line : %d\n", token, pi.linenr);
  290.       }
  291.   if (pi.error == -1)        /*no error */
  292.     return (0);
  293.   /*an error occurred */
  294.   ErrHand (pi.error, pi.linenr);
  295. }                /**************end-of-parser()*/
  296.  
  297.  
  298.  
  299. ErrHand (int which, int nr)    /* fout-afhandeling */
  300. {
  301. /* I designed it this way, to keep the error messages issued from one point*/
  302.   printf ("%s IN LINE %d\n", errtxt[which], nr);
  303. }
  304.  
  305.  
  306. /****************************getvalues(char *line,int *values) *****/
  307. int
  308. getvalues (char *line, int *values)
  309. {
  310.   int i = 0, j = 0, q;
  311.  
  312.   /* scan until first value or ;(remark) or ](end-of-expr)*/
  313.   for (j = 0; j < strlen (line); j++)
  314.     {
  315.       if (line[j] == '#')    /*begin of a variable */
  316.     {
  317.       q = gvar (line + j + 1);
  318.       if ((values[i++] = q) == FULLCRAZY)
  319.         return (-1);
  320.       while (line[++j] != '#') ;    /*continue till end of varname */
  321.       continue;
  322.     }
  323.       if (line[j] == '[')    /*begin of an expression */
  324.     {
  325.       q = evalexp (line + j + 1);
  326.       if ((values[i++] = q) == FULLCRAZY)
  327.         return (-1);    /*error in evaluating*/
  328.       while (line[j] != '@')
  329.         j++;
  330.       line[j] = '©';
  331.     }
  332.       if (ISNUM (line[j]))
  333.     {            /* it's a value !!*/
  334.       values[i++] = atoi (&line[j]);
  335.       if (i >= VALUESMAX)
  336.         break;
  337.       while (ISNUM (line[j]))
  338.         j++;
  339.       j--;
  340.     }
  341.       /* stop with getvalues when: */
  342.       if (line[j] == ';' || line[j] == '\"' || line[j] == ']')
  343.     break;
  344.     }
  345.   return (i);
  346. }
  347.  
  348. char *vars[] =
  349. {"I\0", "J\0", "ON\0", "OFF\0", "ANG\0", "DAN\0", "#"};
  350.  
  351. /*******************************int gvar(char *line) *****/
  352. int
  353. gvar (char *line)
  354. {
  355.   char name[8];
  356.   int teller = 0, welke;
  357.  
  358.   for (teller = 0; line[teller] != '#' && teller < 3; teller++)
  359.     name[teller] = line[teller];/* copy 'line' in 'name' */
  360.   name[teller] = 0;        /* null-terminate string*/
  361.  
  362.   if (teller > 3)
  363.     {
  364.       pi.error = VAREND_ERR;
  365.       return (FULLCRAZY);
  366.     }
  367.   for (welke = 0; vars[welke][0] != '#'; welke++)
  368.     if (!strcmp (name, vars[welke]))
  369.       break;
  370.   if (vars[welke][0] == '#')
  371.     {
  372.       pi.error = NOVAR_ERR;
  373.       return (FULLCRAZY);    /*not a right name*/
  374.     }
  375.   switch (welke)
  376.     {
  377.     case 0:            /* I */
  378.       return (pi.I);
  379.     case 1:            /* J */
  380.       return (pi.J);
  381.     case 2:            /* ON */
  382.       return (ON);
  383.     case 3:            /* OFF */
  384.       return (OFF);
  385.     case 4:            /* ANG */
  386.       return (di.angle & 63);
  387.     case 5:            /* DAN */
  388.       return (di.dangle & 63);
  389.     }
  390.   printf ("this should not occur: welke: %d\n", welke);
  391.   return (FULLCRAZY);        /*HELP!! WE SHOULD NEVER GET THIS FAR!!*/
  392. }                /*end-of-gvar() */
  393.  
  394.  
  395. /*******************************int evalexp(char *line) *****/
  396. int
  397. evalexp (char *line)
  398. {
  399.   int data[VALUESMAX];
  400.   int teller, result = FULLCRAZY;
  401.  
  402.   if (getvalues (line, data) == 2)
  403.     {
  404.       for (teller = 0; teller < strlen (line) && result == FULLCRAZY; teller++)
  405.     switch (line[teller])
  406.       {
  407.       case '*':
  408.         result = data[0] * data[1];
  409.         break;
  410.       case '/':
  411.         if (data[1] == 0)
  412.           {
  413.         pi.error = DIVISION_ERR;
  414.         return (FULLCRAZY);
  415.           }
  416.         result = data[0] / data[1];
  417.         break;
  418.       case '+':
  419.         result = data[0] + data[1];
  420.         break;
  421.       case '_':
  422.         result = data[0] - data[1];
  423.         break;
  424.       }            /* end-of-switch() */
  425.       /* remove the operator */
  426.       if (result != FULLCRAZY)
  427.     line[teller - 1] = '$';
  428.       else
  429.     pi.error = ITTAKESTWO_ERR;    /*shit! no operator*/
  430.       /* check and remove the ] */
  431.       for (teller = 0; line[teller] != ']' && teller < strlen (line); teller++) ;
  432.       if (line[teller] != ']')
  433.     {
  434.       pi.error = PARENTH_ERR;
  435.       result = FULLCRAZY;
  436.     }
  437.       line[teller] = '@';
  438.     }                /*end-of-if*/
  439.   else
  440.     /*not right number of values */
  441.     pi.error = ITTAKESTWO_ERR;
  442.   return (result);
  443. }                /*End-Of-evalexp() */
  444.  
  445. /**************************TakeStr(char *line,char *desstr)**/
  446. TakeStr (char *line, char *desstr)
  447. {
  448.   int teller = 0, pos = 0;
  449.   do
  450.     {
  451.       pos++;
  452.   } while (pos <= strlen (line) && line[pos - 1] != '\"');
  453.   do
  454.     {
  455.       desstr[teller++] = line[pos++];
  456.   } while (pos <= strlen (line) && line[pos] != '\"');
  457.   desstr[teller] = 0;
  458. }
  459.  
  460. /**************************rightnr(real number,required number)*****/
  461. int
  462. rightnr (int realnr, int reqnr)
  463. {
  464.   if (realnr < reqnr)
  465.     {
  466.       pi.error = TOOFEW_ERR;
  467.       errtxt[pi.error][27] = realnr + '0';
  468.       errtxt[pi.error][10] = reqnr + '0';
  469.       return (1);        /* ERROR, line is not executable */
  470.     }
  471.   if (realnr > reqnr)
  472.     {
  473.       pi.error = TOOMUCH_ERR;
  474.       errtxt[pi.error][31] = reqnr + '0';
  475.       return (1);        /* ERROR, line is not executable */
  476.     }
  477.   return (0);            /* wow, right number of values */
  478. }
  479.  
  480.  
  481. /***********************************DoChange(regel)***********
  482.  *   The change-group (0x80 - 0x8f)
  483.  * C  Change
  484.  * [R]  relative    <nr> <type> <add>
  485.  * [A]  absolute    <nr> <type> <value>
  486.  * [M]    more items relative    <from> <upto&including> <type> <add>
  487.  */
  488. DoChange (char *regel, int token)
  489. {
  490.   int i;
  491.  
  492.   switch (token)
  493.     {
  494.     case 0x80:
  495.     case 0x81:
  496.       if (values[1] > 4 || values[1] < 0
  497.       || values[0] < 0 || values[0] >= MXNUMB)
  498.     pi.error = VAL_ERR;
  499.       else if (token == 0x80)
  500.     array[values[0]][values[1]] += values[2];    /* relative ch. */
  501.       else
  502.     array[values[0]][values[1]] = values[2];    /*absolute change */
  503.       break;
  504.  
  505.     case 0x82:
  506.       if (values[1] <= values[0]
  507.       || values[0] < 0
  508.       || values[1] >= MXNUMB
  509.       || values[2] < 0 || values[2] > 4)
  510.     pi.error = VAL_ERR;    /*INCORRECT VALUE */
  511.       else
  512.     for (i = values[0]; i <= values[1]; i++)
  513.       array[i][values[2]] += values[3];
  514.       break;
  515.  
  516.     default:
  517.       pi.error = HEADACHE_ERR;
  518.     }
  519. }
  520.  
  521. /**********************************int stack(int code,int value)***
  522.  *calling:
  523.  * stack(ST_PUSH,id,value)    id=(depth+id) of repeat/gosub etc.
  524.  * value = stack(ST_POP,id,0);    get the value of the stack which represents
  525.  *                the id (nb: depth is ignored)
  526.  * value = stack(ST_QUIT,0,0);    if !0, there's garbage on the stack.
  527.  *
  528.  */
  529. int
  530. stack (int code, int type, long int value)
  531. {
  532.   static int stack[STMAX][2];
  533.   static int stkptr = 0;
  534.   long int ret;
  535.   int tel;
  536.  
  537.   switch (code)
  538.     {
  539.     case ST_INIT:        /* just for symmetry (Teijo, thanks for excuse)*/
  540.       break;
  541.     case ST_PUSH:        /* push something on the stack*/
  542.       if (stkptr < STMAX)
  543.     {
  544.       stack[++stkptr][0] = type;
  545.       stack[stkptr][1] = value;
  546.     }
  547.       break;
  548.     case ST_POP:
  549.       if (stkptr > 0)        /* IS there a stack */
  550.     {
  551.       for (tel = stkptr; tel > 0; tel--)    /* yes, there is a stack */
  552.         if (stack[tel][0] == type)
  553.           {
  554.         ret = stack[tel][1];
  555.         stkptr = tel - 1;    /* decrease the stkptr -> point to prev */
  556.         break;        /* break the for */
  557.           }
  558.       if (tel == 0)        /* unfortunately, there's not what we want */
  559.         ret = ST_NOST;
  560.     }            /* end-of-if */
  561.       else
  562.     ret = ST_NOST;        /* no, there ain't a stack */
  563.       break;
  564.     case ST_QUIT:        /* it is wrong when !0 returned */
  565.       ret = stkptr;
  566.       break;
  567.     }
  568.   return (ret);
  569. }
  570.